import uiconst
import uicls
import uiutil
import uitest
import uthread
import blue
import base
import trinity
import log
import math
DBLCLICKDELAY = 250.0
UTHREADEDEVENTS = (uiconst.UI_CLICK,
 uiconst.UI_KEYUP,
 uiconst.UI_KEYDOWN,
 uiconst.UI_MOUSEMOVE,
 uiconst.UI_MOUSEWHEEL)
eventMap = {uiconst.UI_MOUSEMOVE: 'OnMouseMove',
 uiconst.UI_MOUSEENTER: 'OnMouseEnter',
 uiconst.UI_MOUSEEXIT: 'OnMouseExit',
 uiconst.UI_MOUSEDOWN: 'OnMouseDown',
 uiconst.UI_MOUSEUP: 'OnMouseUp',
 uiconst.UI_CLICK: 'OnClick',
 uiconst.UI_DBLCLICK: 'OnDblClick',
 uiconst.UI_KEYDOWN: 'OnKeyDown',
 uiconst.UI_KEYUP: 'OnKeyUp',
 uiconst.UI_MOUSEWHEEL: 'OnMouseWheel'}
WM_NULL = 0
WM_CREATE = 1
WM_DESTROY = 2
WM_MOVE = 3
WM_SIZE = 5
WM_ACTIVATE = 6
WM_SETFOCUS = 7
WM_KILLFOCUS = 8
WM_ENABLE = 10
WM_SETREDRAW = 11
WM_SETTEXT = 12
WM_GETTEXT = 13
WM_GETTEXTLENGTH = 14
WM_PAINT = 15
WM_CLOSE = 16
WM_QUERYENDSESSION = 17
WM_QUIT = 18
WM_QUERYOPEN = 19
WM_ERASEBKGND = 20
WM_SYSCOLORCHANGE = 21
WM_ENDSESSION = 22
WM_SYSTEMERROR = 23
WM_SHOWWINDOW = 24
WM_CTLCOLOR = 25
WM_WININICHANGE = 26
WM_SETTINGCHANGE = 26
WM_DEVMODECHANGE = 27
WM_ACTIVATEAPP = 28
WM_FONTCHANGE = 29
WM_TIMECHANGE = 30
WM_CANCELMODE = 31
WM_SETCURSOR = 32
WM_MOUSEACTIVATE = 33
WM_CHILDACTIVATE = 34
WM_QUEUESYNC = 35
WM_GETMINMAXINFO = 36
WM_PAINTICON = 38
WM_ICONERASEBKGND = 39
WM_NEXTDLGCTL = 40
WM_SPOOLERSTATUS = 42
WM_DRAWITEM = 43
WM_MEASUREITEM = 44
WM_DELETEITEM = 45
WM_VKEYTOITEM = 46
WM_CHARTOITEM = 47
WM_SETFONT = 48
WM_GETFONT = 49
WM_SETHOTKEY = 50
WM_GETHOTKEY = 51
WM_QUERYDRAGICON = 55
WM_COMPAREITEM = 57
WM_COMPACTING = 65
WM_WINDOWPOSCHANGING = 70
WM_WINDOWPOSCHANGED = 71
WM_POWER = 72
WM_COPYDATA = 74
WM_CANCELJOURNAL = 75
WM_NOTIFY = 78
WM_INPUTLANGCHANGEREQUEST = 80
WM_INPUTLANGCHANGE = 81
WM_TCARD = 82
WM_HELP = 83
WM_USERCHANGED = 84
WM_NOTIFYFORMAT = 85
WM_CONTEXTMENU = 123
WM_STYLECHANGING = 124
WM_STYLECHANGED = 125
WM_DISPLAYCHANGE = 126
WM_GETICON = 127
WM_SETICON = 128
WM_NCCREATE = 129
WM_NCDESTROY = 130
WM_NCCALCSIZE = 131
WM_NCHITTEST = 132
WM_NCPAINT = 133
WM_NCACTIVATE = 134
WM_GETDLGCODE = 135
WM_NCMOUSEMOVE = 160
WM_NCLBUTTONDOWN = 161
WM_NCLBUTTONUP = 162
WM_NCLBUTTONDBLCLK = 163
WM_NCRBUTTONDOWN = 164
WM_NCRBUTTONUP = 165
WM_NCRBUTTONDBLCLK = 166
WM_NCMBUTTONDOWN = 167
WM_NCMBUTTONUP = 168
WM_NCMBUTTONDBLCLK = 169
WM_KEYFIRST = 256
WM_KEYDOWN = 256
WM_KEYUP = 257
WM_CHAR = 258
WM_DEADCHAR = 259
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
WM_SYSCHAR = 262
WM_SYSDEADCHAR = 263
WM_KEYLAST = 264
WM_IME_STARTCOMPOSITION = 269
WM_IME_ENDCOMPOSITION = 270
WM_IME_COMPOSITION = 271
WM_IME_KEYLAST = 271
WM_INITDIALOG = 272
WM_COMMAND = 273
WM_SYSCOMMAND = 274
WM_TIMER = 275
WM_HSCROLL = 276
WM_VSCROLL = 277
WM_INITMENU = 278
WM_INITMENUPOPUP = 279
WM_MENUSELECT = 287
WM_MENUCHAR = 288
WM_ENTERIDLE = 289
WM_CTLCOLORMSGBOX = 306
WM_CTLCOLOREDIT = 307
WM_CTLCOLORLISTBOX = 308
WM_CTLCOLORBTN = 309
WM_CTLCOLORDLG = 310
WM_CTLCOLORSCROLLBAR = 311
WM_CTLCOLORSTATIC = 312
WM_MOUSEFIRST = 512
WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_LBUTTONUP = 514
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDOWN = 516
WM_RBUTTONUP = 517
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDOWN = 519
WM_MBUTTONUP = 520
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522
WM_MOUSEHWHEEL = 526
WM_PARENTNOTIFY = 528
WM_ENTERMENULOOP = 529
WM_EXITMENULOOP = 530
WM_NEXTMENU = 531
WM_SIZING = 532
WM_CAPTURECHANGED = 533
WM_MOVING = 534
WM_POWERBROADCAST = 536
WM_DEVICECHANGE = 537
WM_MDICREATE = 544
WM_MDIDESTROY = 545
WM_MDIACTIVATE = 546
WM_MDIRESTORE = 547
WM_MDINEXT = 548
WM_MDIMAXIMIZE = 549
WM_MDITILE = 550
WM_MDICASCADE = 551
WM_MDIICONARRANGE = 552
WM_MDIGETACTIVE = 553
WM_MDISETMENU = 560
WM_ENTERSIZEMOVE = 561
WM_EXITSIZEMOVE = 562
WM_DROPFILES = 563
WM_MDIREFRESHMENU = 564
WM_IME_SETCONTEXT = 641
WM_IME_NOTIFY = 642
WM_IME_CONTROL = 643
WM_IME_COMPOSITIONFULL = 644
WM_IME_SELECT = 645
WM_IME_CHAR = 646
WM_IME_KEYDOWN = 656
WM_IME_KEYUP = 657
WM_MOUSEHOVER = 673
WM_NCMOUSELEAVE = 674
WM_MOUSELEAVE = 675
WM_CUT = 768
WM_COPY = 769
WM_PASTE = 770
WM_CLEAR = 771
WM_UNDO = 772
WM_RENDERFORMAT = 773
WM_RENDERALLFORMATS = 774
WM_DESTROYCLIPBOARD = 775
WM_DRAWCLIPBOARD = 776
WM_PAINTCLIPBOARD = 777
WM_VSCROLLCLIPBOARD = 778
WM_SIZECLIPBOARD = 779
WM_ASKCBFORMATNAME = 780
WM_CHANGECBCHAIN = 781
WM_HSCROLLCLIPBOARD = 782
WM_QUERYNEWPALETTE = 783
WM_PALETTEISCHANGING = 784
WM_PALETTECHANGED = 785
WM_HOTKEY = 786
WM_PRINT = 791
WM_PRINTCLIENT = 792
WM_HANDHELDFIRST = 856
WM_HANDHELDLAST = 863
WM_PENWINFIRST = 896
WM_PENWINLAST = 911
WM_COALESCE_FIRST = 912
WM_COALESCE_LAST = 927
WM_DDE_FIRST = 992
WM_DDE_INITIATE = 992
WM_DDE_TERMINATE = 993
WM_DDE_ADVISE = 994
WM_DDE_UNADVISE = 995
WM_DDE_ACK = 996
WM_DDE_DATA = 997
WM_DDE_REQUEST = 998
WM_DDE_POKE = 999
WM_DDE_EXECUTE = 1000
WM_DDE_LAST = 1000
WM_USER = 1024
WM_APP = 32768
WM_XBUTTONDOWN = 523
WM_XBUTTONUP = 524
MK_CONTROL = 8
MK_LBUTTON = 1
MK_MBUTTON = 16
MK_RBUTTON = 2
MK_SHIFT = 4
MK_XBUTTON1 = 32
MK_XBUTTON2 = 64
XBUTTON1 = 1
XBUTTON2 = 2
USEUTHREAD = (uiconst.UI_CLICK,
 uiconst.UI_KEYUP,
 uiconst.UI_KEYDOWN)

class Desktop(uicls.NewContainer):
    __guid__ = 'uitest.Desktop'
    default_name = 'desktop'

    def ApplyAttributes(self, attributes):
        uicls.NewContainer.ApplyAttributes(self, attributes)
        self._mouseOver = None
        self._capturingMouseItem = None
        self._mouseX = 0
        self._mouseY = 0
        self._mouseZ = 0
        self._mouseDownX = 0
        self._mouseDownY = 0
        self._mouseDownZ = 0
        self._mouseMoveDeltaX = 0
        self._mouseMoveDeltaY = 0
        self._mouseMoveDeltaZ = 0
        self._mouseTravel = 0
        self._lastAlignmentUpdateTime = None
        self._focus = None
        self._clickTime = None
        self._clickCount = 0
        self._clickTimer = None
        self._mouseButtonStates = {}
        self._unresolvedKeyDown = None
        self._lastKeyDown = None
        self._charsThatCanBlock = set()
        self._cursorSprite = trinity.Tr2Sprite2d()
        self.children.insert(0, self._cursorSprite)
        self._cursorSprite.name = 'cursor'
        self._cursorSprite.displayWidth = 48
        self._cursorSprite.displayHeight = 48
        self._cursorSprite.pickState = uiconst.TR2_SPS_OFF
        self._cursorSprite.texturePrimary = trinity.Tr2Sprite2dTexture()
        self._cursorSprite.texturePrimary.resPath = 'res:/uicore/texture/uitest/uitestcursor.dds'
        self._pickProjection = trinity.TriProjection()
        self._pickView = trinity.TriView()
        self._pickViewport = trinity.TriViewport()
        self.UpdateAlignment()
        uicore.uilib.eventHandler = self.OnAppEvent



    def _OnClose(self, *args):
        uicore.uilib.eventHandler = None
        uicls.NewContainer._OnClose(self, *args)



    def UpdateCursor(self, *args):
        (x, y,) = trinity.GetCursorPos()
        self._cursorSprite.displayX = (x - 24)
        self._cursorSprite.displayY = (y - 24)



    def SetCapture(self, item):
        self._capturingMouseItem = item



    def GetCapture(self):
        return self._capturingMouseItem



    def ReleaseCapture(self, itemReleasing = None):
        self._capturingMouseItem = None



    def OnAppEvent(self, msgID, wParam, lParam):

        def GetItemUnderCursor(_wParam, _lParam):
            mouseX = (_lParam & 65535)
            mouseY = (_lParam >> 16)
            return uicore.scene.PickObject(mouseX, mouseY, self._pickProjection, self._pickView, self._pickViewport)


        for (k, v,) in globals().iteritems():
            if (v == msgID):
                log.LogInfo(('UI:OnAppEvent: %s, params: %s, %s' % (k,
                 wParam,
                 lParam)))
                break

        if (msgID == WM_MOUSEMOVE):
            mouseX = (lParam & 65535)
            mouseY = (lParam >> 16)
            self._mouseMoveDeltaX = (mouseX - self._mouseX)
            self._mouseMoveDeltaY = (mouseY - self._mouseY)
            self._mouseMoveDeltaZ = 0
            self._mouseX = mouseX
            self._mouseY = mouseY
            self._mouseZ = 0
            newMouseOver = GetItemUnderCursor(wParam, lParam)
            lastMouseOver = self._mouseOver
            mouseOverIsNew = bool((lastMouseOver != newMouseOver))
            self._mouseOver = newMouseOver
            mouseCaptureItem = self.GetCapture()
            if mouseCaptureItem:
                self._TryExecuteHandler(uiconst.UI_MOUSEMOVE, object=mouseCaptureItem, wParam=wParam, lParam=lParam)
            elif mouseOverIsNew:
                if lastMouseOver:
                    self._TryExecuteHandler(uiconst.UI_MOUSEEXIT, object=lastMouseOver, wParam=wParam, lParam=lParam)
                if newMouseOver:
                    self._TryExecuteHandler(uiconst.UI_MOUSEENTER, object=newMouseOver, wParam=wParam, lParam=lParam)
            elif newMouseOver:
                self._TryExecuteHandler(uiconst.UI_MOUSEMOVE, object=newMouseOver, wParam=wParam, lParam=lParam)
            self.UpdateHint()
        elif (msgID == WM_LBUTTONDOWN):
            self._mouseButtonStates[uiconst.MOUSELEFT] = True
            self._mouseDownX = self._mouseX
            self._mouseDownY = self._mouseY
            self._mouseDownZ = self._mouseZ
            calledOn = self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, (uiconst.MOUSELEFT), wParam=wParam, lParam=lParam)
            if calledOn:
                self.SetCapture(calledOn)
            if ((not calledOn) or (not uiutil.IsUnder(calledOn, uicore.layer.menu))):
                uiutil.Flush(uicore.layer.menu)
            uicore.registry.SetFocus(calledOn)
        elif (msgID == WM_RBUTTONDOWN):
            self._mouseButtonStates[uiconst.MOUSERIGHT] = True
            self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, (uiconst.MOUSERIGHT), wParam=wParam, lParam=lParam)
        elif (msgID == WM_MBUTTONDOWN):
            self._mouseButtonStates[uiconst.MOUSEMIDDLE] = True
            self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, (uiconst.MOUSEMIDDLE), wParam=wParam, lParam=lParam)
        elif (msgID == WM_XBUTTONDOWN):
            if (wParam & MK_XBUTTON1):
                self._mouseButtonStates[uiconst.MOUSEXBUTTON1] = True
                self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, (uiconst.MOUSEXBUTTON1), wParam=wParam, lParam=lParam)
            else:
                if (wParam & MK_XBUTTON2):
                    self._mouseButtonStates[uiconst.MOUSEXBUTTON2] = True
                    self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, (uiconst.MOUSEXBUTTON2), wParam=wParam, lParam=lParam)
        elif (msgID == WM_LBUTTONUP):
            self._mouseButtonStates[uiconst.MOUSELEFT] = False
            calledOn = self._TryExecuteHandler(uiconst.UI_MOUSEUP, (uiconst.MOUSELEFT), wParam=wParam, lParam=lParam)
            self.ReleaseCapture()
            if calledOn:
                mouseOver = GetItemUnderCursor(wParam, lParam)
                if ((not mouseOver) or (mouseOver is not calledOn)):
                    self._TryExecuteHandler(uiconst.UI_MOUSEEXIT, object=calledOn, wParam=wParam, lParam=lParam)
                    self._TryExecuteHandler(uiconst.UI_MOUSEENTER, object=mouseOver, wParam=wParam, lParam=lParam)
                if (calledOn and (mouseOver is calledOn)):
                    (dblHandlerArgs, dblHandler,) = mouseOver.FindHandler('OnDblClick')
                    (handlerArgs, handler,) = mouseOver.FindHandler('OnClick')
                    if dblHandler:
                        if (self._clickTime and (blue.os.TimeDiffInMs(self._clickTime) < DBLCLICKDELAY)):
                            self._clickCount += 1
                        else:
                            self._clickCount = 1
                        if (self._clickCount >= 2):
                            self._TryExecuteHandler(uiconst.UI_DBLCLICK, object=mouseOver, wParam=wParam, lParam=lParam)
                        elif handler:
                            self._clickTimer = base.AutoTimer(int(DBLCLICKDELAY), self._CheckClickAfterDblClick, mouseOver, wParam, lParam)
                        self._clickTime = blue.os.GetTime()
                    else:
                        if handler:
                            self._TryExecuteHandler(uiconst.UI_CLICK, object=mouseOver, wParam=wParam, lParam=lParam)
        elif (msgID == WM_RBUTTONUP):
            self._mouseButtonStates[uiconst.MOUSERIGHT] = False
            self._TryExecuteHandler(uiconst.UI_MOUSEUP, (uiconst.MOUSERIGHT), wParam=wParam, lParam=lParam)
        elif (msgID == WM_MBUTTONUP):
            self._mouseButtonStates[uiconst.MOUSEMIDDLE] = False
            self._TryExecuteHandler(uiconst.UI_MOUSEUP, (uiconst.MOUSEMIDDLE), wParam=wParam, lParam=lParam)
        elif (msgID == WM_XBUTTONUP):
            if (wParam & MK_XBUTTON1):
                self._mouseButtonStates[uiconst.MOUSEXBUTTON1] = False
                self._TryExecuteHandler(uiconst.UI_MOUSEUP, (uiconst.MOUSEXBUTTON1), wParam=wParam, lParam=lParam)
            else:
                if (wParam & MK_XBUTTON2):
                    self._mouseButtonStates[uiconst.MOUSEXBUTTON2] = False
                    self._TryExecuteHandler(uiconst.UI_MOUSEUP, (uiconst.MOUSEXBUTTON2), wParam=wParam, lParam=lParam)
        elif (msgID == WM_MOUSEWHEEL):
            mouseZ = (wParam >> 16)
            self._mouseMoveDeltaZ = mouseZ
            calledOn = None
            focus = uicore.registry.GetFocus()
            if focus:
                calledOn = self._TryExecuteHandler(uiconst.UI_MOUSEWHEEL, (mouseZ), object=focus, wParam=wParam, lParam=lParam)
            if (calledOn is None):
                callOn = self._TryExecuteHandler(uiconst.UI_MOUSEWHEEL, (mouseZ), wParam=wParam, lParam=lParam)
        if (msgID == WM_KEYDOWN):
            if self._unresolvedKeyDown:
                (_wParam, _lParam,) = self._unresolvedKeyDown
                self._unresolvedKeyDown = None
                self.CheckAccelerators(_wParam, _lParam)
            self._unresolvedKeyDown = (wParam, lParam)
            self._lastKeyDown = (wParam, lParam)
            uthread.new(self.CheckKeyDown, wParam, lParam)
        elif (msgID == WM_CHAR):
            char = wParam
            ignoreChar = False
            (lastwParam, lastlParam,) = self._lastKeyDown
            if (char <= 32):
                ctrl = uicore.GetKeyState(uiconst.VK_CONTROL)
                if ((char not in (uiconst.VK_RETURN,
                 uiconst.VK_BACK,
                 uiconst.VK_SPACE)) or ctrl):
                    ignoreChar = True
            elif (lastwParam in self._charsThatCanBlock):
                alt = uicore.GetKeyState(uiconst.VK_MENU)
                shift = uicore.GetKeyState(uiconst.VK_SHIFT)
                ctrl = uicore.GetKeyState(uiconst.VK_CONTROL)
                function = uicore.cmd.GetFuncByShortcut((ctrl,
                 alt,
                 shift,
                 lastwParam))
                if (function is not None):
                    ignoreChar = True
            if not ignoreChar:
                calledOn = self.ResolveOnChar(wParam, lParam)
                if calledOn:
                    uicore.event.CheckCallbacks(calledOn, uiconst.UI_CHAR, (wParam, lParam))
                    self._unresolvedKeyDown = None
        elif (msgID == WM_KEYUP):
            focus = uicore.registry.GetFocus()
            if focus:
                self._TryExecuteHandler(uiconst.UI_KEYUP, args=(wParam, lParam), object=focus, wParam=wParam, lParam=lParam)
            if (wParam == uiconst.VK_SNAPSHOT):
                try:
                    uicore.cmd.PrintScreen()
                except:
                    pass



    def ResolveOnChar(self, char, flag):
        ignore = (uiconst.VK_RETURN, uiconst.VK_BACK)
        if ((char < 32) and (char not in ignore)):
            return False
        focus = uicore.registry.GetFocus()
        if (focus and (hasattr(focus, 'OnChar') and uiutil.IsVisible(focus))):
            if not blue.win32.IsTransgaming():
                capsLock = uicore.GetKeyState(uiconst.VK_CAPITAL)
                if capsLock:
                    char = ord(unichr(char).upper())
            ret = focus.OnChar(char, flag)
            if ret:
                return focus



    def CheckKeyDown(self, wParam, lParam):
        blue.pyos.synchro.Yield()
        if self._unresolvedKeyDown:
            (wParam, lParam,) = self._unresolvedKeyDown
            self._unresolvedKeyDown = None
            self.CheckAccelerators(wParam, lParam)



    def CheckAccelerators(self, wParam, lParam):
        return uicore.event.CheckAccelerators(wParam, lParam)



    def _TryExecuteHandler(self, eventID, args = None, object = None, wParam = None, lParam = None):
        functionName = eventMap.get(eventID, None)
        if (functionName is None):
            raise NotImplementedError
        itemCapturingMouse = self.GetCapture()
        if itemCapturingMouse:
            callOn = itemCapturingMouse
        elif object:
            callOn = object
        elif lParam:
            mouseX = (lParam & 65535)
            mouseY = (lParam >> 16)
            callOn = uicore.scene.PickObject(mouseX, mouseY, self._pickProjection, self._pickView, self._pickViewport)
        else:
            raise NotImplementedError, 'you have to pass object or lParam to be able to execute event'
        if callOn:
            (handlerArgs, handler,) = callOn.FindHandler(functionName)
            if handler:
                args = (args or ())
                self._ExecuteHandler(eventID, handler, (handlerArgs + args))
            if not handler:
                callOn = None
        return callOn



    def _FindHandler(self, object, handlerName):
        method = getattr(object, handlerName, None)
        if method:
            return ((object), method)
        else:
            method = getattr(object, ('_' + handlerName), None)
            if method:
                return ((), method)
            return (None, None)



    def _CheckClickAfterDblClick(self, object, wParam, lParam):
        self._clickTimer = None
        if (self._clickCount == 1):
            self._TryExecuteHandler(uiconst.UI_CLICK, object=object, wParam=wParam, lParam=lParam)



    def _ExecuteHandler(self, eventID, Handler, args):
        customArgs = ()
        if (type(Handler) == type(())):
            customArgs = Handler[1:]
            Handler = Handler[0]
        if Handler:
            args = (customArgs + args)
            if (eventID in UTHREADEDEVENTS):
                uthread.new(Handler, *args)
            else:
                Handler(*args)



    def CheckUnderCursor(self):
        newMouseOver = uicore.scene.PickObject(self._mouseX, self._mouseY, self._pickProjection, self._pickView, self._pickViewport)
        lastMouseOver = self._mouseOver
        mouseOverIsNew = bool((lastMouseOver != newMouseOver))
        self._mouseOver = newMouseOver
        if mouseOverIsNew:
            if lastMouseOver:
                self._TryExecuteHandler(uiconst.UI_MOUSEEXIT, object=lastMouseOver)
            if newMouseOver:
                self._TryExecuteHandler(uiconst.UI_MOUSEENTER, object=newMouseOver)
        self.UpdateHint()



    def UpdateHint(self):
        uicore.UpdateHint(self._mouseOver)



    def GetMouseOver(self):
        return self._mouseOver



    def AddLayer(self, name, decoClass = None, subLayers = None, idx = -1, loadLayerClass = False):
        decoClass = (decoClass or uicls.Layer)
        layer = decoClass(parent=self, name=name, idx=idx, align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN)
        layer.decoClass = decoClass
        uicore.layerData[name] = (decoClass, subLayers)
        if name.startswith('l_'):
            setattr(uicore.layer, name[2:].lower(), layer)
        else:
            setattr(uicore.layer, name.lower(), layer)
        if (subLayers is not None):
            for (_layerName, _decoClass, _subLayers,) in subLayers:
                layer.AddLayer(_layerName, _decoClass, _subLayers)

        return layer



    def GetLayer(self, name):
        if (name == self.name):
            return self
        for layer in self.children:
            if hasattr(layer, 'GetLayer'):
                found = layer.GetLayer(name)
                if found:
                    return found




    def GetMousePos(self):
        return (self._mouseX, self._mouseY)



    def GetMouseButtonState(self, buttonFlag):
        return self._mouseButtonStates.get(buttonFlag, False)



    def GetMouseMoveDelta(self):
        return (self._mouseMoveDeltaX, self._mouseMoveDeltaY)



    def GetMouseWheelDelta(self):
        return self._mouseMoveDeltaZ



    def GetMouseDownTravel(self):
        if self.GetMouseButtonState(uiconst.MOUSELEFT):
            return math.sqrt((((self._mouseDownX - self._mouseX) * (self._mouseDownX - self._mouseX)) + ((self._mouseDownY - self._mouseY) * (self._mouseDownY - self._mouseY))))
        else:
            return 0




